<?php
/**
 * Description
 * User: duanwenjie
 * Date: 2019/5/9
 * Time: 11:59 AM
 */

namespace app\index\service;
use app\common\ConfigBase;
use app\common\model\ToolModel;
use app\common\service\DownService;
use think\Db;
use think\Exception;

class ShopwarehouseoutService
{
    static public function getList($param, $is_download = false)
    {
        try{
            $where = "where 1 = 1 ";
            $pageNumber = isset($param['page']) ? $param['page'] : 1;
            $pageData = isset($param['limit']) ? $param['limit'] : 20;
            $warehouse_shop_permission = ConfigBase::getWarehouseShopPermission();  // 仓库权限
            $id = isset($param['id']) ? $param['id'] : '';  // ID
            $base_warehouse_id = isset($param['base_warehouse_id']) ? $param['base_warehouse_id'] : '';  // 收货仓库ID
            $batch = isset($param['batch']) ? $param['batch'] : '';  // 出库批次号
            $type = isset($param['type']) ? $param['type'] : '';  // 出库类型
            $business_sn = isset($param['business_sn']) ? $param['business_sn'] : '';  // 出库业务单号
            $create_time = isset($param['create_time']) ? $param['create_time'] : '';  // 出库时间
            $status = isset($param['status']) ? $param['status'] : '';  // 状态
            $offset = ($pageNumber - 1) * $pageData;
            $limit = " LIMIT $offset,$pageData";

            if (!empty($id)) {
                $id = trim($id);
                $where .= " AND id = $id";
            }
            if (!empty($base_warehouse_id)) {
                $base_warehouse_id = trim($base_warehouse_id);
                $where .= " AND base_warehouse_id = $base_warehouse_id";
            }
            if (!empty($type)) {
                $type = trim($type);
                $where .= " AND type = {$type}";
            }
            if (!empty($batch)) {
                $batch = trim($batch);
                $where .= " AND batch = '{$batch}'";
            }
            if (!empty($business_sn)) {
                $business_sn = trim($business_sn);
                $where .= " AND business_sn = '{$business_sn}'";
            }
            if (!empty($create_time)) {
                $date = explode(' - ', $create_time);
                if (count($date) == 2){
                    $where .= " AND create_time >= '$date[0]'";
                    $where .= " AND create_time <= '$date[1]'";
                }
            }
            if (!empty($status)) {
                $where .= " AND status = {$status}";
            }
            if (!empty($warehouse_shop_permission)) {
                $warehouse_shop_permission = trim($warehouse_shop_permission);
                $where .= " AND base_warehouse_id in ($warehouse_shop_permission)";
            }else{
                $where .= " AND base_warehouse_id in ('')";
            }

            $sqlCount = "SELECT COUNT(id) num FROM shop_warehouse_out {$where}";
            $countArr = ToolModel::queryData($sqlCount);
            if (empty($countArr) || $countArr[0]['num'] == 0) {
                if ($is_download) exitJson(["code" => "500", "msg" => "无有效数据"]);
                return array('total' => 0, 'list' => array());
            }
            $fileds = 'id,base_warehouse_id,base_warehouse_name,batch,business_sn,sku,sku_name,
                      need_quantity,quantity,price,unit,operator,update_time,create_time,type,status,
                      case type when 0 then "新建" when 1 then "调拨出库" when 2 then "销售出库" when 3 then "盘亏出库" end type_name,
                      case status when 1 then "已确定" when -1 then "未确定" end status_name';

            $sql = "SELECT {$fileds} FROM shop_warehouse_out {$where} ORDER BY id DESC {$limit}";
            if ($is_download) return "SELECT {$fileds} FROM shop_warehouse_out {$where} ORDER BY id DESC ";
            $list = ToolModel::queryData($sql);
            foreach ($list as &$v){
                if ($v['operator'] == "") $v['update_time'] = "";
            }
            $data = array();
            $data['total'] = intval($countArr[0]['num']);
            $data['list'] = $list;

            return $data;
        }catch (Exception $e){
            trace($e->getMessage(), 'error');
            throw new Exception($e->getMessage());
        }
    }



    /**
     * 导出数据
     * @param $param
     * @return array
     * @author duanwenjie
     */
    static public function export($param)
    {
        $sql = self::getList($param, true);
        $title = array(
            'base_warehouse_name' => '仓库',
            'batch' => '出库批次号',
            'business_sn' => '出库业务单号',
            'sku' => 'SKU',
            'sku_name' => 'SKU名称',
            'need_quantity' => '需求数量',
            'quantity' => '实际数量',
            'price' => '单价',
            'type_name' => '出库类型',
            'create_time' => '出库时间',
            'operator' => '操作人',
            'update_time' => '操作时间',
            'status_name' => '状态'
        );
        $res = DownService::getData($sql, $title, '', $param);

        return $res;
    }


    /**
     * 编辑/确定店仓出库
     * 更新店仓成本/明细
     * @param $param
     * @return array
     * @author duanwenjie
     */
    static public function edit($param)
    {
        try{
            $is_sure = isset($param['is_sure']) ? true : false;
            $is_sap = isset($param['is_sap']) ? true : false;
            $status = '';
            $type = '';
            $update_data = array();
            $check_shop_warehouse_cost = array();
            $update_shopwarehousecost_data = array();
            $update_shopwarehousecostdetail_data = array();
            if (!empty($param)){
                $update_data[] = array(
                    "id" => $param['id'],
                    "quantity" => $param['quantity'],
                    "operator" => $param['operator'],
                    "status" => ($is_sure) ? 1 : -1
                );
                // 店仓成本更新数据，店仓成本明细插入数据
                $check_shop_warehouse_cost = Db::name('shop_warehouse_cost')
                    ->field('*')
                    ->where('base_warehouse_id', '=', $param['base_warehouse_id'])
                    ->where('surplus_quantity', '>', 0)// 批次结余大于0的数据
                    ->where('sku', '=', $param['sku'])
                    ->order('create_time', 'asc')// 时间升序，先入先出原则
                    ->select();
                // 获取当前操作数据的状态,类型
                $result = Db::name('shop_warehouse_out')->field('status,type')->where('id', '=', $param['id'])->find();
                $status = !empty($result) ? $result['status'] : '';
                $type = !empty($result) ? $result['type']  : '';
            }else{
                return array("code" => 500, "msg" => "操作数据为空");
            }

            // 确定出库,数据状态为未确定,才走店仓成本更新、库存管理更新操作
            // 出库状态 状态 -1：未确定 1：已确定 （只有是未确定的数据才允许出库处理）
            if ($is_sure && $status == -1){
                //== 店仓出库操作 ==
                //加文件锁避免多人同时操作
                ToolModel::startTrans();
                try{
                    $file = FILE_PATH . "shopwarehouseout_lock.txt";
                    $fp = fopen($file, 'w');
                    if ($fp === false){
                        ToolModel::rollback();
                        return array("code" => 500, "msg" => "系统繁忙,操作失败!");
                    }
                    if (flock($fp, LOCK_EX | LOCK_NB)){
                        /*店仓出库，店仓成本更新成本明细，先入先出原则插入出库批次号*/
                        if (!empty($check_shop_warehouse_cost)){
                            $can_quantity = array_column($check_shop_warehouse_cost, 'surplus_quantity');
                            $all_quantity = array_sum($can_quantity);
                            if ($all_quantity < $param['quantity']){
                                ToolModel::rollback();
                                return array("code" => 500, "msg" => "店仓成本表中没有合适的SKU数据进行出库处理");
                            }
                            $need_quantity = $param['quantity']; // 需要出库的数量
                            $temp_price = 0;
                            foreach ($check_shop_warehouse_cost as $key => $value){
                                if ($need_quantity > 0){ // 大于0表示还需要再次选择另一个批次的SKU进行出库
                                    $update_shopwarehousecostdetail_data[] = array(
                                        "shop_cost_id" => $value['id'], // 店仓成本ID
                                        "batch" => $param['batch'], // 出库批次号
                                        "business_sn" => $param['business_sn'], // 出库业务单号
                                        "quantity" => ($value['surplus_quantity'] > $need_quantity) ? $need_quantity : $value['surplus_quantity']
                                    );
                                    $update_shopwarehousecost_data[] = array(
                                        "id" => $value['id'],
                                        "surplus_quantity" => ($value['surplus_quantity'] > $need_quantity) ? ($value['surplus_quantity'] - $need_quantity) : 0
                                    );
                                    /*SAP订单要计算入库批次加权单价 (入库批次数量/需要出库的数量) * 入库批次单价 */
                                    $temp_price += ($value['surplus_quantity'] > $need_quantity) ? ($need_quantity / $param['quantity']) * $value['price'] : ($value['surplus_quantity'] / $param['quantity']) * $value['price'];
                                    $need_quantity = $need_quantity - $value['surplus_quantity'];
                                }else{
                                    break;
                                }
                            }
                            /*SAP订单要计算加权单价，非SAP订单要type = 1,调拨出库的要生成一条未确定的店仓入库记录*/
                            if ($is_sap){
                                $update_data[0]['price'] = $temp_price;
                            }else{
                                if ($type == 1){
                                    $insert_shopwarehousein_data = array();
                                    $insert_shopwarehousein_detail_data = array();
                                    $res = Db::name('distribution_plan')
                                        ->join('distribution_plan_detail','distribution_plan.id = distribution_plan_detail.distribution_plan_id','left')
                                        ->join('base_warehouse','distribution_plan.warehouse_id_rec = base_warehouse.id','left')
                                        ->join('allocate_order','distribution_plan.code = allocate_order.code','left')
                                        ->field('distribution_plan.*,distribution_plan_detail.sku,distribution_plan_detail.sku_name,distribution_plan_detail.quantity,
                                                       distribution_plan_detail.price,base_warehouse.warehouse_name as base_warehouse_name')
                                        ->where('allocate_order.allocate_order_sn','=', $param['business_sn'])
                                        ->select();
                                    if (!empty($res)){
                                        $batch = ToolModel::createSerialNumber('RK1'); // 入库批次号
                                        $insert_shopwarehousein_data = array(
                                            "batch" => $batch,
                                            "base_warehouse_id" => $res[0]['warehouse_id_rec'], // 店仓入库 => 配送计划收货仓库
                                            "base_warehouse_name" => $res[0]['base_warehouse_name'], // 店仓入库仓库名称
                                            "business_sn" => $param['business_sn'],
                                            "sku_type" => count($res), // SKU种类
                                            "type" => 1, // 入库类型 1：调拨入库 2：采购入库 3：盘盈入库
                                            "operator" => $res[0]['operator']
                                        );
                                        /*如果店仓入库已有记录，则只添加到入库明细表*/
                                        $id = Db::name('shop_warehouse_in')->where('business_sn','=',$param['business_sn'])->value('id');
                                        if ($id){
                                            $shop_warehouse_in_id = $id;
                                        }else{
                                            $shop_warehouse_in_id = ToolModel::insertData($insert_shopwarehousein_data, 'shop_warehouse_in');
                                        }
                                        if ($shop_warehouse_in_id){
                                            foreach ($res as $value_){
                                                if ($value_['sku'] == $param['sku']){
                                                    $insert_shopwarehousein_detail_data[] = array(
                                                        "shop_warehouse_in_id" => $shop_warehouse_in_id,
                                                        "sku" => $value_['sku'],
                                                        "sku_name" => $value_['sku_name'],
                                                        "quantity" => $value_['quantity'], // 数量 => 实际入库数量
                                                        "quantity_in" => $value_['quantity'], // 入库数量 => 实际入库数量
                                                        "price" => $temp_price // 取店仓成本批次加权单价
                                                    );
                                                }
                                            }
                                            if (!empty($insert_shopwarehousein_detail_data)) $res2 = ToolModel::dbInsertOrUpdate('shop_warehouse_in_detail', $insert_shopwarehousein_detail_data);
                                        }
                                    }
                                }
                            }
                        }else{
                            ToolModel::rollback();
                            return array("code" => 500, "msg" => "店仓成本表中没有合适的SKU数据进行出库处理");
                        }
                        if (!empty($update_shopwarehousecost_data)) $res = ToolModel::dbInsertOrUpdate('shop_warehouse_cost', $update_shopwarehousecost_data);
                        if (!empty($update_shopwarehousecostdetail_data)) $res2 = ToolModel::dbInsertOrUpdate('shop_warehouse_cost_detail', $update_shopwarehousecostdetail_data);
                        // 插入完店仓成本数据后，再更新一次库存管理的实物库存、库存成本、加权单价、库龄数据
                        if (!empty($check_shop_warehouse_cost)){
                            $sku_infos = ShopwarehouseinService::getAllSkuStockInfos([$param['sku']], $param['base_warehouse_id']);
                            $update_shop_warehouse_stock_data_ = array_values($sku_infos);
                            if (!empty($sku_infos)) ToolModel::dbInsertOrUpdate('shop_warehouse_stock', $update_shop_warehouse_stock_data_);
                        }
                        ToolModel::commit();
                        ToolModel::closeFp($fp);
                    }else{
                        ToolModel::rollback();
                        fclose($fp);
                        return array("code" => 500, "msg" => "系统繁忙,请刷新页面后再操作!");
                    }
                }catch (Exception $e){
                    ToolModel::rollback();
                    trace($e->getMessage(), 'error');
                    !empty($fp) && fclose($fp);
                    return array("code" => 600, "msg" => '失败' . $e->getMessage());
                }
            }

            if (!empty($update_data)) $res3 = ToolModel::dbInsertOrUpdate('shop_warehouse_out', $update_data); // 更新店仓出库数据信息
            return array("code" => 1, "msg" => "操作成功");
        }catch (Exception $e){
            trace($e->getMessage(), 'error');
            return array("code" => 600, "msg" => '失败' . $e->getMessage());
        }
    }
}